home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
pasblk.zip
/
PASBLK.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1990-05-04
|
35KB
|
805 lines
{-----------------------------------------------------------------------------}
{ Program PasBlk 1.5 900428 }
{ Show nested block structures in different colors }
{ Written By: John W. Fowler, Pres., Global Solutions }
{ Monochrome-display enhancements provided by Ron Schuster }
{-----------------------------------------------------------------------------}
Uses DOS, CRT;
Type
LineRecType = Record { used to store display line }
Chars: String[80]; { and its color attributes }
LineNum: Word; { on the heap }
ChangeCol: Array[1..20] of Byte;
Colors: Array[0..20] of Byte;
End;
LineRecTypePtr = ^LineRecType;
Var
PasPgm: Text;
PgmLine,FilNam,TmpLine: String;
CurrntLen,I,L,C,NLines,Color0,BG0,NColors,NRecs,
State,L1End,L2Home,L1,L2,NestDepth,BlkDelimType: Integer;
Dummy,UserChar: Char;
LineRec: Array[1..2500] of LineRecTypePtr;
TmpColors: Array[0..20] of Byte;
TmpChangeCol: Array[1..20] of Byte;
SeekUntil,NeedPaint: Boolean;
VideoMode,ScreenWidth,DisplayPage,MaxColors: Byte;
Const
ColorStack: Array[1..7] of Integer = (15,10,12,9,13,11,14);
IsNotUnit: Boolean = True;
InRecord: Boolean = False;
TruncErr: Boolean = False;
Label SetUpLine,ShowIt,Clear,Quit;
{---------------------------------------------------------------------------}
Procedure GetTextAttr(Var C: Char; Var Attr: Integer);
{ This procedure calls Interrupt $10, Function 8: Get Character/Attribute }
Var
Regis: Registers;
Begin
With Regis Do Begin
AH := 8; BH := 0; {page 0}
Intr($10,Regis);
C := Chr(AL); Attr := AH;
End;
End; {GetTextAttr}
{---------------------------------------------------------------------------}
Procedure GetVideoMode(Var VideoMode,ScreenWidth,DisplayPage: Byte);
{ This procedure calls Interrupt $10, Function $0F: get video mode }
Var
Regs: Registers;
Begin
With Regs Do Begin
AH := 15; {Get current video mode}
Intr($10,Regs);
VideoMode := AL;
ScreenWidth := AH;
DisplayPage := BH;
End; {with Regs}
End; {GetVideoMode}
{---------------------------------------------------------------------------}
Procedure PressRETURN;
Begin
Write('Press ENTER to continue... '); ReadLn;
End; {PressRETURN}
{---------------------------------------------------------------------------}
Procedure TooMuch;
Begin
TextColor(12);
WriteLn('Too many color changes on the same line ',
'( > 20); line no. = ',NLines);
WriteLn('Unable to process this file.'); PressRETURN;
End; {TooMuch}
{---------------------------------------------------------------------------}
Procedure SetLabelAttrs(OnOff: Integer);
Begin
If OnOff = 1 Then Begin
TextBackground(1); TextColor(15); End
Else TextBackground(0);
End; {SetLabelAttrs}
{---------------------------------------------------------------------------}
Procedure ExpandTabs;
Var N,L,Col: Integer;
Begin
While Pos(#9,PgmLine) > 0 Do Begin
N := Pos(#9,PgmLine);
Col := 8*Succ(N div 8);
PgmLine[N] := ' ';
For L := 1 to (Col-N) Do Insert(' ',PgmLine,N);
End; {While}
End; {ExpandTabs}
{---------------------------------------------------------------------------}
Function NextRecOK: Boolean;
Begin
If NRecs = 2500 Then Begin
TextColor(12); WriteLn(#7); WriteLn('More than 2500 lines found;');
WriteLn('only the first 2500 can be displayed by this version.');
PressRETURN; NextRecOK := False; Exit;
End;
If MaxAvail > SizeOf(LineRecType) Then Begin
Inc(NRecs); New(LineRec[NRecs]);
NextRecOK := True; End
Else Begin
TextColor(12); WriteLn(#7,'Insufficient RAM to display entire file;');
WriteLn('only the first ',Pred(NLines),' lines can be displayed.');
PressRETURN; NextRecOK := False;
End;
End; {NextRecOK}
{---------------------------------------------------------------------------}
Function NewColor(DC: Integer): Integer;
Begin { push (DC > 0) or pop (DC < 0) color stack }
C := C + DC;
If C > MaxColors Then C := 1;
If C < 1 Then C := MaxColors;
NewColor := ColorStack[C];
End; {NewColor}
{---------------------------------------------------------------------------}
Procedure DoScroll(N: Integer);
{ This procedure uses Interupt $10, Function 6 to scroll part of the screen }
Var
Regs: Registers;
Begin
With Regs Do Begin
AH := 6; If N < 0 Then AH := 7;
AL := 0; If N <> 0 Then AL := 1;
BH := 0;
CH := 2; CL := 0;
DH := 23; DL := 79;
Intr($10,Regs);
End; {With Regs}
End; {DoScroll}
{---------------------------------------------------------------------------}
Procedure ShowL1L2; { show the range of the displayed lines in }
Var LL1,LL2: Integer; { terms of their original line numbers }
Begin
LL1 := LineRec[L1]^.LineNum;
LL2 := LineRec[L2]^.LineNum;
SetLabelAttrs(1); GotoXY(41,1);Write(' '); GotoXY(38,1);
Write(LL1,'-',LL2,' '); SetLabelAttrs(0); GotoXY(1,25);
TextColor(0); Write(' ',#8); { hide cursor }
End; {ShowL1L2}
{---------------------------------------------------------------------------}
Procedure ShowLine(L: Integer); { display a line with its attributes }
Var
I,N,C: Integer;
Begin
With LineRec[L]^ Do Begin
N := 1; C := Colors[0] and 15; { get initial line color }
TextColor(C);
If Colors[0] > 15
Then Begin TextBackground(C); TextColor(0); End
Else TextBackground(0);
For I := 1 to Length(Chars) Do Begin { run through the line, }
While I = ChangeCol[N] Do Begin { changing attributes where }
C := Colors[N] and 15; { the ChangeCol array says to }
TextColor(C); { and displaying each character }
If Colors[N] > 15
Then Begin TextBackground(C); TextColor(0); End
Else TextBackground(0);
If N < 20 Then Inc(N);
End; {I = ChangeCol[N]}
Write(Chars[I]);
End; {For I}
End; {With LineRec}
End; {ShowLine}
{---------------------------------------------------------------------------}
Procedure ShowHome; { display the top of the file }
Var L: Integer;
Begin
If L1 = 1 Then Exit; { if already at top, exit }
DoScroll(0); { clear file-display part of screen }
For L := 1 to L2Home Do Begin { loop over lines at top of file }
GotoXY(1,L+2); ShowLine(L); { and display them }
End; {For L}
L1 := 1; L2 := L2Home; { record current top & bottom line numbers }
End; {ShowHome}
{---------------------------------------------------------------------------}
Procedure ShowCurrent; { display a page of the file }
Var LL: Integer;
Begin
DoScroll(0); { clear file-display part of screen }
If KeyPressed Then Exit; { don't keep user waiting }
LL := 3; { start display at line 3 }
NeedPaint := False; { clear flag; screen will soon be fresh }
For L := L1 to L2 Do Begin { loop through requested lines }
GotoXY(1,Ll); ShowLine(L); Inc(LL); { and display them }
End; {For L}
End; {ShowCurrent}
{---------------------------------------------------------------------------}
Function SetReverse(OnOff: Integer): Integer; { set attributes for }
Var L: Integer; { reverse video on/off }
Begin
If NColors = 20 Then Begin
TooMuch; SetReverse := -1; PressRETURN; Exit;
End;
Inc(NColors);
TmpColors[NColors] := ColorStack[C];
If OnOff < 1 Then
If VideoMode = 7 Then
TmpColors[NColors] := $1F
Else
TmpColors[NColors] := ColorStack[C] + 32;
If I + OnOff < 2 Then Begin
TmpColors[0] := TmpColors[NColors];
For L := 1 to NColors Do TmpChangeCol[L] := 0;
NColors := 0;
End {If I ...}
Else TmpChangeCol[NColors] := I + OnOff;
SetReverse := 1;
End; {SetReverse}
{---------------------------------------------------------------------------}
Procedure ChkBeginEnd;
Var L: Integer;
Label ChkRecord;
Begin
BlkDelimType := 0;
If TmpLine[I] = 'N' Then Begin { check for BEGIN }
If I < 5 Then Exit;
If TmpLine[Pred(I)] <> 'I' Then Exit;
If TmpLine[I-2] <> 'G' Then Exit;
If TmpLine[I-3] <> 'E' Then Exit;
If TmpLine[I-4] <> 'B' Then Exit;
If I > 5 Then Begin
L := I - 5;
If not (TmpLine[L] in [' ',';',':','}'])
Then If not ((I > 6) and (TmpLine[Pred(L)] = '*')
and (TmpLine[L] = ')'))
Then Exit; {not BEGIN}
End; {If I > 5}
If CurrntLen > I Then Begin
L := Succ(I);
If not (TmpLine[L] in [' ','{'])
Then If not ((CurrntLen > L) and (TmpLine[L] = '(')
and (TmpLine[Succ(L)] = '*'))
Then Exit; {not BEGIN}
End; {If CurrntLen > I}
BlkDelimType := 1; {it is a BEGIN}
End {BEGIN}
Else Begin { check for END }
If I < 3 Then Exit;
If TmpLine[Pred(I)] <> 'N' Then Goto ChkRecord;
If TmpLine[I-2] <> 'E' Then Exit;
If I > 3 Then Begin
L := I - 3;
If not (TmpLine[L] in [' ',';',':','}'])
Then If not ((I > 4) and (TmpLine[Pred(L)] = '*')
and (TmpLine[L] = ')'))
Then Exit; {not END}
End; {If I > 3}
If CurrntLen > I Then Begin
L := Succ(I);
If not (TmpLine[L] in [' ',';','{','.'])
Then If not ((CurrntLen > L) and (TmpLine[L] = '(')
and (TmpLine[Succ(L)] = '*'))
Then Exit; {not END}
End; {If CurrntLen > I}
BlkDelimType := 2; {it is an END}
InRecord := False;
End; {END}
Exit;
ChkRecord:
If I < 6 Then Exit;
If TmpLine[Pred(I)] <> 'R' Then Exit;
If TmpLine[I-2] <> 'O' Then Exit;
If TmpLine[I-3] <> 'C' Then Exit;
If TmpLine[I-4] <> 'E' Then Exit;
If TmpLine[I-5] <> 'R' Then Exit;
If I > 6 Then Begin
L := I - 6;
If not (TmpLine[L] in [' ',';',':','}'])
Then If not ((I > 7) and (TmpLine[Pred(L)] = '*')
and (TmpLine[L] = ')'))
Then Exit; {not RECORD}
End; {If I > 6}
If CurrntLen > I Then Begin
L := Succ(I);
If not (TmpLine[L] in [' ','{'])
Then If not ((CurrntLen > L) and (TmpLine[L] = '(')
and (TmpLine[Succ(L)] = '*'))
Then Exit; {not RECORD}
End; {If CurrntLen > I}
BlkDelimType := 3; {it is a RECORD}
InRecord := True;
End; {ChkBeginEnd}
{---------------------------------------------------------------------------}
Procedure ChkRepUntil;
Var L: Integer;
Label TryUnit,ChkObject;
Begin
BlkDelimType := 0;
If TmpLine[I] = 'T' Then Begin { check for REPEAT }
If I < 6 Then Goto TryUnit;
If TmpLine[Pred(I)] <> 'A' Then Goto TryUnit;
If TmpLine[I-2] <> 'E' Then Exit;
If TmpLine[I-3] <> 'P' Then Exit;
If TmpLine[I-4] <> 'E' Then Exit;
If TmpLine[I-5] <> 'R' Then Exit;
If I > 6 Then Begin
L := I - 6;
If not (TmpLine[L] in [' ',';',':','}'])
Then If not ((I > 7) and (TmpLine[Pred(L)] = '*')
and (TmpLine[L] = ')'))
Then Exit; {Not REPEAT}
End; {If I > 6}
If CurrntLen > I Then Begin
L := Succ(I);
If not (TmpLine[L] in [' ','{'])
Then If not ((CurrntLen > L) and (TmpLine[L] = '(')
and (TmpLine[Succ(L)] = '*'))
Then Exit; {not REPEAT}
End; {If CurrntLen > I}
BlkDelimType := 1; {it is a REPEAT}
End {REPEAT}
Else Begin { check for UNTIL }
If I < 5 Then Exit;
If TmpLine[Pred(I)] <> 'I' Then Exit;
If TmpLine[I-2] <> 'T' Then Exit;
If TmpLine[I-3] <> 'N' Then Exit;
If TmpLine[I-4] <> 'U' Then Exit;
If I > 5 Then Begin
L := I - 5;
If not (TmpLine[L] in [' ',';',':','}'])
Then If not ((I > 6) and (TmpLine[Pred(L)] = '*')
and (TmpLine[L] = ')'))
Then Exit; {not UNTIL}
End; {If I > 5}
If CurrntLen > I Then Begin
L := Succ(I);
If not (TmpLine[L] in [' ',';','{'])
Then If not ((CurrntLen > L) and (TmpLine[L] = '(')
and (TmpLine[Succ(L)] = '*'))
Then Exit; {not UNTIL}
End; {If CurrntLen > I}
BlkDelimType := 2; {it is an UNTIL}
End; {UNTIL}
Exit;
TryUnit: { check for UNIT }
If I < 4 Then Goto ChkObject;
If TmpLine[Pred(I)] <> 'I' Then Goto ChkObject;
If TmpLine[I-2] <> 'N' Then Exit;
If TmpLine[I-3] <> 'U' Then Exit;
If I > 4 Then Begin
L := I - 4;
If not (TmpLine[L] in [' ',';',':','}'])
Then If not ((I > 5) and (TmpLine[Pred(L)] = '*')
and (TmpLine[L] = ')'))
Then Exit; {Not UNIT}
End; {If I > 4}
If CurrntLen > I Then Begin
L := Succ(I);
If not (TmpLine[L] in [' ','{'])
Then If not ((CurrntLen > L) and (TmpLine[L] = '(')
and (TmpLine[Succ(L)] = '*'))
Then Exit; {not UNIT}
End; {If CurrntLen > I}
BlkDelimType := 3; {it is a UNIT}
IsNotUnit := False;
Exit;
ChkObject:
If I < 6 Then Exit;
If TmpLine[Pred(I)] <> 'C' Then Exit;
If TmpLine[I-2] <> 'E' Then Exit;
If TmpLine[I-3] <> 'J' Then Exit;
If TmpLine[I-4] <> 'B' Then Exit;
If TmpLine[I-5] <> 'O' Then Exit;
If I > 6 Then Begin
L := I - 6;
If not (TmpLine[L] in [' ',';',':','}'])
Then If not ((I > 7) and (TmpLine[Pred(L)] = '*')
and (TmpLine[L] = ')'))
Then Exit; {not OBJECT}
End; {If I > 6}
If CurrntLen > I Then Begin
L := Succ(I);
If not (TmpLine[L] in [' ','(','{'])
Then Exit; {not OBJECT}
End; {If CurrntLen > I}
BlkDelimType := 4; {it is an OBJECT}
End; {ChkRepUntil}
{---------------------------------------------------------------------------}
Function NoSplit(C: Char): Boolean; { return True if C is a letter }
Begin
NoSplit := (C in ['A'..'Z']) or (C in ['a'..'z']);
End; {NoSplit}
{---------------------------------------------------------------------------}
Procedure ChkCase;
Var L: Integer;
Begin
BlkDelimType := 0; { check for CASE }
If InRecord Then Exit;
If I < 4 Then Exit;
If TmpLine[Pred(I)] <> 'S' Then Exit;
If TmpLine[I-2] <> 'A' Then Exit;
If TmpLine[I-3] <> 'C' Then Exit;
If I > 4 Then Begin
L := I - 4;
If not (TmpLine[L] in [' ',';',':','}'])
Then If not ((I > 5) and (TmpLine[Pred(L)] = '*')
and (TmpLine[L] = ')'))
Then Exit; {not CASE}
End; {If I > 4}
If CurrntLen > I Then Begin
L := Succ(I);
If not (TmpLine[L] in [' ','{'])
Then If not ((CurrntLen > L) and (TmpLine[L] = '(')
and (TmpLine[Succ(L)] = '*'))
Then Exit; {not CASE}
End; {If CurrntLen > I}
BlkDelimType := 1; {it is a CASE}
End; {ChkCase}
{---------------------------------------------------------------------------}
Begin
GetVideoMode(VideoMode,ScreenWidth,DisplayPage); { check for color display }
GetTextAttr(Dummy,Color0);
BG0 := Color0 ShR 4; Color0 := Color0 and $F;
TextBackground(0);
If VideoMode = 7 Then Begin
MaxColors := 4;
TextColor(15);
End
Else Begin
MaxColors := 7;
TextColor(9);
End;
ClrScr; WriteLn;
WriteLn('--------------------------------------------------',
'---------------------------');
WriteLn(' PasBlk 1.5 Pascal ',
'Block Nesting Display');
WriteLn(' Copyright (C) 1990 Global Solutions ',
'All Rights Reserved');
WriteLn(' This Utility May Be Distributed Free of Charge ',
'Not to be Sold');
WriteLn('-----------------------------------------------------------',
'------------------');
WriteLn;
{ if no command-line input, give tutorial }
If (ParamCount = 0) Then Begin
WriteLn('Usage: PASBLK file'); WriteLn;
WriteLn('where: file = name of the Pascal program file to be displayed');
WriteLn(' (if no extension, ".PAS" will be assumed;',
' to indicate that');
WriteLn(' there is no extension, place a period at the end)');
WriteLn;
WriteLn(' The file will be displayed with each block structure shown');
Write ('in a different ');
If VideoMode = 7 Then
Write('attribute (the attribute')
Else
Write('color (the color');
WriteLn(' sequence wraps around if block ');
WriteLn('nesting goes deeper than ',MaxColors,
'); comments are in reverse video.');
WriteLn;
WriteLn(' The cursor control keys may be used to control scrolling');
WriteLn('while the file is being displayed on the monitor. The Esc key');
WriteLn('may be used to halt execution.');
WriteLn;
WriteLn('Limitations: 2500 displayed lines (wrapped lines count as ',
'multiple lines);');
WriteLn(' Displayed lines must fit in RAM;');
Write (' 20 or fewer ');
If VideoMode = 7 Then
Write('attribute')
Else
Write('color');
WriteLn(' changes per displayed line.');
WriteLn; PressRETURN; Goto Quit;
End;
If VideoMode = 7 Then Begin
ColorStack[1] := 7;
ColorStack[2] := 1;
ColorStack[3] := 15;
ColorStack[4] := 9;
End; {If VideoMode = 7}
{ get file name for Pascal program }
FilNam := ParamStr(1); { first parameter should be file name }
If Pos('.',FilNam) = 0 Then FilNam := FilNam + '.Pas';
Assign (PasPgm, FilNam);
{$I-} Reset(PasPgm) {$I+};
{ if error on open, give diagnostic }
If (IOResult > 0) Then Begin
WriteLn(#7,'Unable to open file: ',FilNam); PressRETURN;
Goto Quit;
End;
{ initialize; clip file name if necessary }
C := 1; NLines := 0; NRecs := 0;
State := 0; NestDepth := 0; SeekUntil := False;
While Pos('\',FilNam) > 0 Do Delete(FilNam,1,Pos('\',FilNam));
WriteLn('File: ',FilNam);
Write('Reading line ');
{ read file and prepare heap records }
While Not EOF(PasPgm) Do Begin
ReadLn(PasPgm, PgmLine); Inc(NLines);
GotoXY(14,9); Write(NLines);
ExpandTabs;
SetUpLine:
If Length(PgmLine) > 80
Then If (PgmLine[80] <> ' ') and (PgmLine[81] <> ' ')
Then If NoSplit(PgmLine[80])
Then Begin
I := 80;
While NoSplit(PgmLine[I]) and (I > 40) Do Dec(I);
If (I > 40) Then Begin
Inc(I);
For L := I to 80 Do Insert(' ',PgmLine,I);
If (Length(PgmLine) + 80 - I) > 255 Then TruncErr := True;
End
Else TruncErr := True;
End;
If Length(PgmLine) > 160
Then If (PgmLine[160] <> ' ') and (PgmLine[161] <> ' ')
Then If NoSplit(PgmLine[160])
Then Begin
I := 160;
While NoSplit(PgmLine[I]) and (I > 120) Do Dec(I);
If (I > 120) Then Begin
Inc(I);
For L := I to 160 Do Insert(' ',PgmLine,I);
If (Length(PgmLine) + 160 - I) > 255 Then TruncErr := True;
End
Else TruncErr := True;
End;
CurrntLen := Length(PgmLine); NColors := 0; TmpLine := PgmLine;
For I := 1 to CurrntLen Do TmpLine[I] := UpCase(TmpLine[I]);
For I := 1 to 20 Do TmpChangeCol[I] := 0;
For I := 1 to CurrntLen Do Begin
If I = 1 Then Begin
TmpColors[0] := ColorStack[C];
If State > 2 Then TmpColors[0] := ColorStack[C] + 32;
End; {If I = 1}
Case State of
0: Begin { not currently in quotes or comment }
Case TmpLine[I] of
'N','D': Begin
ChkBeginEnd; {sets BlkDelimType}
If BlkDelimType > 0 Then Begin
If NColors = 20 Then Begin TooMuch; Goto Quit; End;
Inc(NColors);
If BlkDelimType = 1 Then Begin
TmpColors[NColors] := NewColor(1);
Inc(NestDepth);
If I = 5 Then Begin
TmpColors[0] := TmpColors[NColors];
For L := 1 to NColors Do TmpChangeCol[L] := 0;
NColors := 0;
End {If I = 5}
Else TmpChangeCol[NColors] := I - 4;
End {If BlkDelimType = 1}
Else If BlkDelimType = 2 Then Begin
TmpColors[NColors] := NewColor(-1);
Dec(NestDepth);
If CurrntLen > Succ(I)
Then TmpChangeCol[NColors] := I + 2
Else Begin
TmpChangeCol[NColors] := 0; Dec(NColors);
End; {Else}
End; {Else [BlkDelimType = 2]}
If BlkDelimType = 3 Then Begin
TmpColors[NColors] := NewColor(1);
Inc(NestDepth);
If I = 6 Then Begin
TmpColors[0] := TmpColors[NColors];
For L := 1 to NColors Do TmpChangeCol[L] := 0;
NColors := 0;
End {If I = 6}
Else TmpChangeCol[NColors] := I - 5;
End {If BlkDelimType = 3}
End; {If BlkDelimType > 0}
End; { Begin..End block }
'T','L': Begin
ChkRepUntil; {sets BlkDelimType}
If BlkDelimType > 0 Then Begin
If NColors = 20 Then Begin TooMuch; Goto Quit; End;
Inc(NColors);
If BlkDelimType = 1 Then Begin
TmpColors[NColors] := NewColor(1);
Inc(NestDepth);
If I = 6 Then Begin
TmpColors[0] := TmpColors[NColors];
For L := 1 to NColors Do TmpChangeCol[L] := 0;
NColors := 0;
End {If I = 6}
Else TmpChangeCol[NColors] := I - 5;
End {If BlkDelimType = 1}
Else If BlkDelimType = 2 Then SeekUntil := True;
If BlkDelimType = 3 Then Begin { UNIT }
TmpColors[NColors] := NewColor(1);
Inc(NestDepth);
If I = 4 Then Begin
TmpColors[0] := TmpColors[NColors];
For L := 1 to NColors Do TmpChangeCol[L] := 0;
NColors := 0;
End {If I = 4}
Else TmpChangeCol[NColors] := I - 3;
End; {If BlkDelimType = 3}
If BlkDelimType = 4 Then Begin { OBJECT }
TmpColors[NColors] := NewColor(1);
Inc(NestDepth);
If I = 6 Then Begin
TmpColors[0] := TmpColors[NColors];
For L := 1 to NColors Do TmpChangeCol[L] := 0;
NColors := 0;
End {If I = 6}
Else TmpChangeCol[NColors] := I - 5;
End {If BlkDelimType = 4}
End; {If BlkDelimType > 0}
End; { Repeat..Until block }
'E': Begin
ChkCase; {sets BlkDelimType}
If BlkDelimType > 0 Then Begin
If NColors = 20 Then Begin TooMuch; Goto Quit; End;
Inc(NColors);
If BlkDelimType = 1 Then Begin
TmpColors[NColors] := NewColor(1);
Inc(NestDepth);
If I = 4 Then Begin
TmpColors[0] := TmpColors[NColors];
For L := 1 to NColors Do TmpChangeCol[L] := 0;
NColors := 0;
End {If I = 6}
Else TmpChangeCol[NColors] := I - 3;
End {If BlkDelimType = 1}
End; {If BlkDelimType > 0}
End; { Case.. block beginning }
';': If SeekUntil Then Begin
SeekUntil := False;
TmpColors[NColors] := NewColor(-1);
Dec(NestDepth);
If CurrntLen > I Then TmpChangeCol[NColors] := Succ(I);
End;
#39: State := 1; { state 1 is in '....' }
(* '"': State := 2; *) { state 2 is in "...." }
'*': If I > 1 { state 3 is in (*....*) }
Then If PgmLine[Pred(I)] = '('
Then Begin
State := 3; If SetReverse(-1) < 0 Then Goto Quit;
End; {entered state 3}
'{': Begin (* state 4 is in {....} *)
State := 4; If SetReverse(0) < 0 Then Goto Quit;
End; {entered state 4}
End; {Case PgmLine[I]}
End; {0}
1: If PgmLine[I] = #39 Then State := 0; { currently in '....' }
(* 2: If PgmLine[I] = '"' Then State := 0; *) { currently in "...." }
3: If PgmLine[I] = ')' { currently in (*....*) }
Then If I > 1
Then If PgmLine[Pred(I)] = '*'
Then Begin
State := 0; If SetReverse(1) < 0 Then Goto Quit;
End; {3}
4: If PgmLine[I] = '}' Then Begin (* currently in {....} *)
State := 0; If SetReverse(1) < 0 Then Goto Quit;
End; {4}
End; {Case State}
{ process wraparound }
If I = 80 Then Begin
If not NextRecOK Then Goto ShowIt; { increments NRecs & allocates }
With LineRec[NRecs]^ Do Begin { next heap record }
For L := 0 to NColors Do Colors[L] := TmpColors[L];
For L := 1 to 20 Do ChangeCol[L] := TmpChangeCol[L];
LineNum := NLines;
Chars := Copy(PgmLine,1,80); Delete(PgmLine,1,80);
End; {With LineRec}
If Length(PgmLine) > 0 Then Goto SetUpLine;
End; {If I = 80}
End; {For I}
{ put line on heap if not just done as part of wraparound }
If CurrntLen <> 80 Then Begin
If not NextRecOK Then Goto ShowIt; { increments NRecs & allocates }
With LineRec[NRecs]^ Do Begin { next heap record }
For L := 0 to NColors Do Colors[L] := TmpColors[L];
For L := 1 to 20 Do ChangeCol[L] := TmpChangeCol[L];
LineNum := NLines;
Chars := Copy(PgmLine,1,80); Delete(PgmLine,1,80);
End; {With LineRec}
End; {If CurrntLen}
If KeyPressed Then Begin
While KeyPressed Do Dummy := ReadKey;
GotoXY(1,10); Write('Abort (y/n) ? ');
Repeat Dummy := UpCase(ReadKey) Until Dummy in ['N','Y'];
If Dummy = 'Y' Then Goto Quit;
GotoXY(1,10); ClrEoL;
End; {If KeyPressed}
End; {While Not EOF(PasPgm)}
Close(PasPgm); If SeekUntil Then If NestDepth >= 0 Then Inc(NestDepth)
Else Dec(NestDepth);
If NestDepth <> 0 Then If (IsNotUnit or (NestDepth <> 1)) Then Begin
WriteLn; I := NestDepth;
If not IsNotUnit Then Dec(I);
If Abs(I) = 1 Then Write('A') Else Write(Abs(I));
Write(' block nesting error');
If Abs(I) = 1 Then Write(' was') Else Write('s were');
WriteLn(' found.',#7); PressRETURN;
End; {If NestDepth}
If TruncErr Then Begin
WriteLn(#7);
WriteLn('Line truncation occurred; block nesting errors may result.');
If (not IsNotUnit and (NestDepth = 1)) or (IsNotUnit and (NestDepth = 0))
Then WriteLn('Nesting levels completed normally, however.');
WriteLn(
'Check lines that were broken in the middle of a word for display wraparound');
WriteLn(
'and lines that may have been extended beyond 255 columns in order to insert');
WriteLn(
'blanks (to avoid wrapping in the middle of a word); block-delimiting keywords');
WriteLn(
'can be missed by the program in such cases.');
PressRETURN;
End; {If TruncErr}
ShowIt:
GotoXY(1,1); ClrScr; SetLabelAttrs(1);
Write(' File: Lines ',
' Total Lines: ');
GotoXY(8,1); Write(FilNam); GotoXY(74,1); Write(NLines);
GotoXY(1,2); Write(' Active Keys: '#24,' ',#25,
' PgUp PgDn Home End Esc to Exit ');
SetLabelAttrs(0);
L1End := NRecs - 21; If L1End < 1 Then L1End := 1;
L2Home := 22; If NRecs < 22 Then L2Home := NRecs;
L1 := -9; ShowHome; NeedPaint := False;
Repeat
If NeedPaint Then ShowCurrent;
ShowL1L2;
UserChar := ReadKey; If UserChar = #27 Then Goto Clear;
If (UserChar = #0) and KeyPressed Then Begin
UserChar := ReadKey;
Case UserChar of
#71: ShowHome; { Home }
#72: If L1 > 1 Then Begin { Up }
DoScroll(-1); Dec(L1); Dec(L2);
GotoXY(1,3); ShowLine(L1);
End; {72}
#73: If L1 > 1 Then Begin { PgUp }
I := L1 - 18; If I < 1 Then I := 1;
For L := 1 to L1-I Do Begin
Dec(L1);
If not KeyPressed Then Begin
DoScroll(-1); GotoXY(1,3); ShowLine(L1);
End
Else NeedPaint := True;
End; {For L}
L2 := L1 + 21;
If L2 > NRecs Then L2 := NRecs;
End; {73}
#79: If L1 < L1End Then Begin { End }
DoScroll(0); I := 2;
For L := L1End to NRecs Do Begin
Inc(I); GotoXY(1,I); ShowLine(L);
End; {For L}
L1 := L1End; L2 := NRecs;
End; {79}
#80: If L1 < L1End Then Begin { Down }
DoScroll(1); Inc(L1); Inc(L2);
GotoXY(1,24); ShowLine(L2);
End; {80}
#81: If L1 < L1End Then Begin { PgDn }
I := L1 + 18; If I > L1End Then I := L1End;
For L := 1 to I-L1 Do Begin
Inc(L2);
If not KeyPressed Then Begin
DoScroll(1); GotoXY(1,24); ShowLine(L2);
End
Else NeedPaint := True;
End; {For L}
L1 := I;
End; {81}
End; {Case UserChar}
End; {If UserChar = 0...}
Until UserChar = #27;
Clear:
ClrScr; For I := 1 to 25 Do WriteLn;
Quit:
TextColor(Color0); TextBackground(BG0); ClrScr;
End.